package org.dromara.common.json.utils

import cn.hutool.core.lang.Dict
import cn.hutool.core.util.ArrayUtil
import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.exc.MismatchedInputException
import org.dromara.common.core.exception.ServiceException
import org.dromara.common.core.utils.SpringUtils.getBean
import org.dromara.common.core.utils.StringUtils
import java.io.IOException

/**
 * JSON 工具类
 *
 * @author  芋道源码
 * @updater LikeYouDo
 * @date 2025/1/6 16:24
 */
object JsonUtils {
    private val OBJECT_MAPPER: ObjectMapper = getBean(ObjectMapper::class.java)

    @JvmStatic
    fun getObjectMapper(): ObjectMapper = OBJECT_MAPPER

    /**
     * 将对象转换为JSON格式的字符串
     *
     * @param obj 要转换的对象
     * @return JSON格式的字符串，如果对象为null，则返回null
     * @throws RuntimeException 如果转换过程中发生JSON处理异常，则抛出运行时异常
     */
    @JvmStatic
    fun toJsonString(obj: Any?): String {
        try {
            return OBJECT_MAPPER.writeValueAsString(obj)
        } catch (e: JsonProcessingException) {
            throw RuntimeException(e)
        }
    }

    /**
     * 将JSON格式的字符串转换为指定类型的对象
     *
     * @param text  JSON格式的字符串
     * @param clazz 要转换的目标对象类型
     * @param <T>   目标对象的泛型类型
     * @return 转换后的对象，如果字符串为空则返回null
     * @throws RuntimeException 如果转换过程中发生IO异常，则抛出运行时异常
     */
    @JvmStatic
    fun <T> parseObject(text: String, clazz: Class<T>?): T {
        if (StringUtils.isEmpty(text)) {
            throw ServiceException("json字符串为空")
        }
        try {
            return OBJECT_MAPPER.readValue(text, clazz)
        } catch (e: IOException) {
            throw RuntimeException(e)
        }
    }

    /**
     * 将字节数组转换为指定类型的对象
     *
     * @param bytes 字节数组
     * @param clazz 要转换的目标对象类型
     * @param <T>   目标对象的泛型类型
     * @return 转换后的对象，如果字节数组为空则返回null
     * @throws RuntimeException 如果转换过程中发生IO异常，则抛出运行时异常
     */
    @JvmStatic
    fun <T> parseObject(bytes: ByteArray?, clazz: Class<T>?): T? {
        if (ArrayUtil.isEmpty(bytes)) {
            return null
        }
        try {
            return OBJECT_MAPPER.readValue(bytes, clazz)
        } catch (e: IOException) {
            throw RuntimeException(e)
        }
    }

    /**
     * 将JSON格式的字符串转换为指定类型的对象，支持复杂类型
     *
     * @param text          JSON格式的字符串
     * @param typeReference 指定类型的TypeReference对象
     * @param <T>           目标对象的泛型类型
     * @return 转换后的对象，如果字符串为空则返回null
     * @throws RuntimeException 如果转换过程中发生IO异常，则抛出运行时异常
     */
    @JvmStatic
    fun <T> parseObject(text: String?, typeReference: TypeReference<T>?): T? {
        if (StringUtils.isBlank(text)) {
            return null
        }
        try {
            return OBJECT_MAPPER.readValue(text, typeReference)
        } catch (e: IOException) {
            throw RuntimeException(e)
        }
    }

    /**
     * 将JSON格式的字符串转换为Dict对象
     *
     * @param text JSON格式的字符串
     * @return 转换后的Dict对象，如果字符串为空或者不是JSON格式则返回null
     * @throws RuntimeException 如果转换过程中发生IO异常，则抛出运行时异常
     */
    @JvmStatic
    fun parseMap(text: String?): Dict? {
        if (StringUtils.isBlank(text)) {
            return null
        }
        return try {
            OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.typeFactory.constructType(Dict::class.java))
        } catch (e: MismatchedInputException) {
            // 类型不匹配说明不是json
            null
        } catch (e: IOException) {
            throw RuntimeException(e)
        }
    }

    /**
     * 将JSON格式的字符串转换为Dict对象的列表
     *
     * @param text JSON格式的字符串
     * @return 转换后的Dict对象的列表，如果字符串为空则返回null
     * @throws RuntimeException 如果转换过程中发生IO异常，则抛出运行时异常
     */
    @JvmStatic
    fun parseArrayMap(text: String?): List<Dict>? {
        if (StringUtils.isBlank(text)) {
            return null
        }
        try {
            return OBJECT_MAPPER.readValue(
                text,
                OBJECT_MAPPER.typeFactory.constructCollectionType(
                    MutableList::class.java,
                    Dict::class.java
                )
            )
        } catch (e: IOException) {
            throw RuntimeException(e)
        }
    }

    /**
     * 将JSON格式的字符串转换为指定类型对象的列表
     *
     * @param text  JSON格式的字符串
     * @param clazz 要转换的目标对象类型
     * @param <T>   目标对象的泛型类型
     * @return 转换后的对象的列表，如果字符串为空则返回空列表
     * @throws RuntimeException 如果转换过程中发生IO异常，则抛出运行时异常
     */
    @JvmStatic
    fun <T> parseArray(text: String?, clazz: Class<T>?): List<T> {
        if (StringUtils.isEmpty(text)) {
            return ArrayList()
        }
        try {
            return OBJECT_MAPPER.readValue(
                text,
                OBJECT_MAPPER.typeFactory.constructCollectionType(
                    MutableList::class.java,
                    clazz
                )
            )
        } catch (e: IOException) {
            throw RuntimeException(e)
        }
    }
}
